package server

import (
	"go/ast"
	"net"
	"ylm.minidb/backend/utils"
	"ylm.minidb/transporter"
)

type Server interface {
	Start()
}

type server struct {
	network string
	address string

	tbm tbm.TableManager
}

func NewServer(network, adress string, tbm tbm.TableManager) *server {
	return &server{network: network, address: adress, tbm: tbm}
}
func (s *server) Start() {
	listener, err := net.Listen(s.network, s.address)
	if err != nil {
		panic(err)
	}
	utils.Info("Server Start at ", s.network, s.address)
	for {
		conn, err := listener.Accept()
		if err != nil {
			utils.Warn(err)
			continue
		}
		go s.serve(conn)
	}
}

func (s *server) serve(conn net.Conn) {
	var netErr error

	utils.Info("New connection from", conn.RemoteAddr())

	defer func() {
		utils.Info("Close connection from", conn.RemoteAddr(), " NetErr: ", netErr)
		conn.Close()
	}()

	tr := transporter.NewHexTransporter(conn)
	pr := transporter.NewProtocol()
	packager := transporter.NewPackager(tr, pr)

	defer packager.Close()
	var pkg transporter.Package

	var exe Executor

	exe = NewExecutor(s.tbm)
	defer exe.Close()

	for {
		pkg, netErr = packager.Receive()
		if nerErr != nil {
			break
		}

		sql := pkg.Data()
		result, sqlErr := exe.Execute(sql)
		pkg = transporter.NewPackage(result, sqlErr)

		netErr = packager.Send(pkg)
		if netErr != nil {
			break
		}
	}
}
